package com.codefish.framework.spring.aop.framework.autoproxy;

import com.codefish.framework.spring.aop.IClassFilter;
import com.codefish.framework.spring.aop.IPointcutAdvisor;
import com.codefish.framework.spring.aop.framework.AdviseSupport;
import com.codefish.framework.spring.aop.framework.DefaultAopProxyFactory;
import com.codefish.framework.spring.aop.framework.IAopProxyFactory;
import com.codefish.framework.spring.aop.target.SingletonTargetResource;
import com.codefish.framework.spring.beans.exception.BeansException;
import com.codefish.framework.spring.beans.factory.config.IBeanPostProcessor;
import org.aopalliance.intercept.MethodInterceptor;

/**
 * 自动生成代理对象,并通过bean的生命周期替换掉被代理的bean实例
 *
 * @author <a href='https://gitee.com/hzf2281'>codefish</a>
 * @version 1.0.0
 * @since 2022/11/01 下午 02:29
 */
public class DefaultAdvisorAutoProxyCreator implements IBeanPostProcessor {
    /**
     * AOP动态代理Advisor
     */
    IPointcutAdvisor advisor;
    /**
     * 是否开启代理目标类，如果为true则采用CGlib代理，默认为true
     */
    Boolean proxyTargetClass = true;

    public DefaultAdvisorAutoProxyCreator() {

    }

    public void setAdvisor(IPointcutAdvisor advisor) {
        this.advisor = advisor;
    }

    public void setProxyTargetClass(boolean proxyTargetClass) {
        this.proxyTargetClass = proxyTargetClass;
    }


    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        IClassFilter classFilter = advisor.getPointcut().getClassFilter();
        if (classFilter.matches(bean.getClass())) {
            //创建Aop代理工厂
            IAopProxyFactory factory = new DefaultAopProxyFactory();
            //配置AdviseSupport
            AdviseSupport adviseSupport = new AdviseSupport();
            //设置要代理的目标资源
            adviseSupport.setTargetResource(new SingletonTargetResource(bean));
            //设置是否代理对象的类(开启CGlib代理)
            adviseSupport.setProxyTargetClass(proxyTargetClass);
            //设置切面的切入方法位置
            adviseSupport.setMethodMatcher(advisor.getPointcut().getMethodMatcher());
            //设置切面的advice
            adviseSupport.setMethodInterceptor((MethodInterceptor) advisor.getAdvice());
            //生成代理对象实例并返回
            return factory.createAopProxy(adviseSupport).getProxy();
        }
        return bean;

    }

}
